/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
/**
 * @author Igor V. Stolyarov
 */
package com.jgraph.gaeawt.java.awt.image;

import org.apache.harmony.awt.internal.nls.Messages;

import com.jgraph.gaeawt.java.awt.Transparency;
import com.jgraph.gaeawt.java.awt.color.ColorSpace;

public abstract class PackedColorModel extends ColorModel
{
	public PackedColorModel(ColorSpace space, int bits, int colorMaskArray[],
			int alphaMask, int trans)
	{

		super(bits, createBits(colorMaskArray, alphaMask), space,
				(alphaMask == 0 ? false : true), trans);

		if (pixel_bits < 1 || pixel_bits > 32)
		{
			// awt.236=The bits is less than 1 or greater than 32
			throw new IllegalArgumentException(Messages.getString("awt.236")); //$NON-NLS-1$
		}

		componentMasks = new int[3];
		for (int i = 0; i < 3; i++)
		{
			componentMasks[i] = colorMaskArray[i];
		}

		if (hasAlpha)
		{
			componentMasks[3] = alphaMask;
			if (this.bits[3] == 1)
			{
				transparency = Transparency.BITMASK;
			}
		}

		parseComponents();
	}

	public PackedColorModel(ColorSpace space, int bits, int rmask, int gmask,
			int bmask, int amask, int trans)
	{

		super(bits, createBits(rmask, gmask, bmask, amask), space,
				(amask == 0 ? false : true), trans);

		if (pixel_bits < 1 || pixel_bits > 32)
		{
			// awt.236=The bits is less than 1 or greater than 32
			throw new IllegalArgumentException(Messages.getString("awt.236")); //$NON-NLS-1$
		}

		for (int i = 0; i < 3; i++)
		{
			if (cs.getMinValue(i) != 0.0f || cs.getMaxValue(i) != 1.0f)
			{
				// awt.23A=The min/max normalized component values are not 0.0/1.0
				throw new IllegalArgumentException(
						Messages.getString("awt.23A")); //$NON-NLS-1$
			}
		}
		componentMasks = new int[numComponents];
		componentMasks[0] = rmask;
		componentMasks[1] = gmask;
		componentMasks[2] = bmask;

		if (hasAlpha)
		{
			componentMasks[3] = amask;
			if (this.bits[3] == 1)
			{
				transparency = Transparency.BITMASK;
			}
		}

		parseComponents();
	}

	@Override
	public SampleModel createCompatibleSampleModel(int w, int h)
	{
		return new SinglePixelPackedSampleModel(w, h,
				componentMasks);
	}

	public final int getMask(int index)
	{
		return componentMasks[index];
	}

	public final int[] getMasks()
	{
		return (componentMasks.clone());
	}

	private static int[] createBits(int colorMaskArray[], int alphaMask)
	{
		int bits[];
		int numComp;
		if (alphaMask == 0)
		{
			numComp = colorMaskArray.length;
		}
		else
		{
			numComp = colorMaskArray.length + 1;
		}

		bits = new int[numComp];
		int i = 0;
		for (; i < colorMaskArray.length; i++)
		{
			bits[i] = countCompBits(colorMaskArray[i]);
			if (bits[i] < 0)
			{
				// awt.23B=The mask of the {0} component is not contiguous
				throw new IllegalArgumentException(Messages.getString(
						"awt.23B", i)); //$NON-NLS-1$
			}
		}

		if (i < numComp)
		{
			bits[i] = countCompBits(alphaMask);

			if (bits[i] < 0)
			{
				// awt.23C=The mask of the alpha component is not contiguous
				throw new IllegalArgumentException(
						Messages.getString("awt.23C")); //$NON-NLS-1$
			}
		}

		return bits;
	}

	private static int[] createBits(int rmask, int gmask, int bmask, int amask)
	{

		int numComp;
		if (amask == 0)
		{
			numComp = 3;
		}
		else
		{
			numComp = 4;
		}
		int bits[] = new int[numComp];

		bits[0] = countCompBits(rmask);
		if (bits[0] < 0)
		{
			// awt.23D=The mask of the red component is not contiguous
			throw new IllegalArgumentException(Messages.getString("awt.23D")); //$NON-NLS-1$
		}

		bits[1] = countCompBits(gmask);
		if (bits[1] < 0)
		{
			// awt.23E=The mask of the green component is not contiguous
			throw new IllegalArgumentException(Messages.getString("awt.23E")); //$NON-NLS-1$
		}

		bits[2] = countCompBits(bmask);
		if (bits[2] < 0)
		{
			// awt.23F=The mask of the blue component is not contiguous
			throw new IllegalArgumentException(Messages.getString("awt.23F")); //$NON-NLS-1$
		}

		if (amask != 0)
		{
			bits[3] = countCompBits(amask);
			if (bits[3] < 0)
			{
				// awt.23C=The mask of the alpha component is not contiguous
				throw new IllegalArgumentException(
						Messages.getString("awt.23C")); //$NON-NLS-1$
			}
		}

		return bits;
	}

	private static int countCompBits(int compMask)
	{
		int bits = 0;
		if (compMask != 0)
		{
			// Deleting final zeros
			while ((compMask & 1) == 0)
			{
				compMask >>>= 1;
			}
			// Counting component bits
			while ((compMask & 1) == 1)
			{
				compMask >>>= 1;
				bits++;
			}
		}

		if (compMask != 0)
		{
			return -1;
		}

		return bits;
	}
}
